package com.japhet.stripesdemo.business.stripe;

import com.alibaba.fastjson.JSONObject;
import com.japhet.stripesdemo.business.stripe.VO.ConfigResponseVO;
import com.japhet.stripesdemo.business.stripe.BO.StripeCheckPayResBO;
import com.japhet.stripesdemo.business.stripe.BO.StripeGetBindCardListBO;
import com.japhet.stripesdemo.business.stripe.BO.StripePaymentIntentBO;
import com.japhet.stripesdemo.business.stripe.VO.StripeGetBindCardListVO;
import com.japhet.stripesdemo.common.ResponseR;
import com.japhet.stripesdemo.dao.entity.User;
import com.japhet.stripesdemo.dao.service.UserService;
import com.stripe.exception.StripeException;
import com.stripe.model.Event;
import com.stripe.model.PaymentIntent;
import com.stripe.model.PaymentMethod;
import com.stripe.net.Webhook;
import com.stripe.param.PaymentIntentCreateParams;
import com.xiaoleilu.hutool.json.JSONUtil;
import io.github.cdimascio.dotenv.Dotenv;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("stripe")
public class StripeController {

    @Autowired
    private Dotenv dotenv;

    @Autowired
    private StripeService stripeService;

    @Autowired
    private UserService userService;

    /**
     * 配置， 获取公钥 key
     * @return
     */
    @GetMapping("config")
    public String config() {
        ConfigResponseVO configResponseVO = new ConfigResponseVO(dotenv.get("STRIPE_PUBLISHABLE_KEY"));
        return JSONUtil.toJsonStr(configResponseVO);
    }

    /**
     * 已绑定卡列表
     * @param stripeGetBindCardListBO
     * @return
     * @throws StripeException
     */
    @PostMapping("bindCardList")
    public List<StripeGetBindCardListVO> getBindCardList(@RequestBody StripeGetBindCardListBO stripeGetBindCardListBO) throws StripeException {

        List<StripeGetBindCardListVO> voList = new ArrayList<>();
        List<PaymentMethod> paymentMethodList = stripeService.customerCardList(stripeGetBindCardListBO.getCustomerId());
        for(PaymentMethod paymentMethod : paymentMethodList) {
//            System.out.println("Payment Method ID: " + paymentMethod.getId());
//            System.out.println("Card Brand: " + paymentMethod.getCard().getBrand());
//            System.out.println("Card Last 4 Digits: " + paymentMethod.getCard().getLast4());
            StripeGetBindCardListVO vo = new StripeGetBindCardListVO();
            vo.setPaymentMethodId(paymentMethod.getId());
            vo.setCardBrand(paymentMethod.getCard().getBrand());
            vo.setLast4Digits(paymentMethod.getCard().getLast4());
            voList.add(vo);
        }
        return voList;
    }

    /**
     * 创建预付- 前端拿到客户端动态密钥后 去确认支付
     * @param stripePaymentIntentBO
     * @return
     * @throws StripeException
     */
    @PostMapping("paymentIntent")
    public String paymentIntent(@RequestBody StripePaymentIntentBO stripePaymentIntentBO) throws StripeException {
        User user = userService.getById(stripePaymentIntentBO.getUserId());
        Long price = stripePaymentIntentBO.getPrice().multiply(new BigDecimal(1000)).longValue();
        // 创建 PaymentIntent
        PaymentIntent paymentIntent = PaymentIntent.create(
                new PaymentIntentCreateParams.Builder()
                        .setCustomer(user.getStripeCustomerId())
                        .setCurrency("cad")
                        .setAmount(price)  // 金额以分为单位
                        .build()
        );
        return JSONUtil.toJsonStr(paymentIntent);
    }

    /**
     * 检查支付结果
     * @param stripeCheckPayResBO
     * @return
     * @throws StripeException
     */
    @PostMapping("checkPayRes")
    public String checkPayRes(@RequestBody StripeCheckPayResBO stripeCheckPayResBO) throws StripeException {
        ResponseR r = ResponseR.ok().message("经服务端验证，支付成功");
        // 使用 PaymentIntent.retrieve 方法检查支付状态
        PaymentIntent paymentIntent = PaymentIntent.retrieve(stripeCheckPayResBO.getPaymentIntentId());
        System.out.println(JSONUtil.toJsonStr(paymentIntent));
        if (!StringUtils.equals(paymentIntent.getStatus(), "succeeded")) {
            r = ResponseR.error().message("经服务端验证，支付失败");
        }

        return JSONUtil.toJsonStr(r.message("充值成功"));
    }

    @PostMapping("useAlipay")
    public String useAlipay(@RequestBody StripePaymentIntentBO stripePaymentIntentBO) throws StripeException {
        Long price = stripePaymentIntentBO.getPrice().multiply(new BigDecimal(1000)).longValue();
        PaymentIntentCreateParams params =
                PaymentIntentCreateParams.builder()
                        .setAmount(price)
                        //这里需要使用 人民币 的币值三字码
                        .setCurrency("cny")
                        .addPaymentMethodType("alipay")
                        .addPaymentMethodType("wechat_pay")
                        //这里就不用了
//                        .setAutomaticPaymentMethods(
//                                PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
//                                        .setEnabled(true)
//                                        .build()
//                        )
                        .build();
        PaymentIntent paymentIntent = PaymentIntent.create(params);
        return JSONUtil.toJsonStr(paymentIntent);
    }

    @ResponseBody
    @RequestMapping(value = {"/api/pay/stripe/stripe_events"}, method = RequestMethod.POST)
    public void stripe_events(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("------进入回调了------");
        try {
            String endpointSecret = "whsec_vInPmYjyKxxxxxxxxxxxxxxxxx";//webhook秘钥签名
            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*4];
            int n = 0;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            String payload = new String(bytes, "UTF-8");
            String sigHeader = request.getHeader("Stripe-Signature");
            Event event = Webhook.constructEvent(payload, sigHeader, endpointSecret);//验签，并获取事件

            PaymentIntent intent = (PaymentIntent) event
                    .getDataObjectDeserializer()
                    .getObject()
                    .get();

            switch(event.getType()) {
                case "checkout.session.completed"://支付完成
                    System.out.println("---------------success2222222---------------");
                    String s = event.getDataObjectDeserializer().getObject().get().toJson();
                    JSONObject jsonObject = JSONObject.parseObject(s);
                    JSONObject jsonObject2 = (JSONObject)jsonObject.get("metadata");
                    String orderId = jsonObject2.getString("orderId");
                    System.out.println("订单号为："+orderId);
                    System.out.println("根据订单号从数据库中找到订单，并将状态置为支付成功状态");
                    break;
                case "checkout.session.expired"://过期
                    System.out.println("---------------checkout.session.expired---------------");
                    break;
                case "payment_intent.created"://创建订单 这里事件就是图二选着的事件
                    System.out.println("---------------nnnnnnnnnnnnnnnnnnnnnn---------------");
                    break;
                case "payment_intent.canceled"://取消订单
                    System.out.println("---------------canceledcanceledcanceledcanceledcanceledcanceled---------------");
                    break;
                case "payment_intent.succeeded"://支付成功
                    if(intent.getStatus().equals("succeeded")) {
                        System.out.println("---------------success---------------");
                        Map<String,String> metaData = intent.getMetadata();//自定义传入的参数
                        String orderId2 = metaData.get("orderId");//自定义订单号
                        System.out.println("订单号为："+orderId2);
                        System.out.println("根据订单号从数据库中找到订单，并将状态置为支付成功状态");
                        //*********** 根据订单号从数据库中找到订单，并将状态置为成功 *********//*
                    }
                    break;
                case "payment_intent.payment_failed"://支付失败
                    System.out.println("Failed: " + intent.getId());
                    System.out.println("---------------payment_failed---------------");
                    break;

                default:
                    break;
            }
        } catch (Exception e) {
            System.out.println("stripe异步通知（webhook事件）"+e);
        }
    }
}
